/**
 * 20220117:从原SoftLine分离
 */
import HardLineMaterial from "./hard-line-material";

/**
 * 拐角连续厚度线材质
 * @param values {object} 可选参数对象
 *      {
 *          zoomFactor：1，{number} 长度UV缩放
 *          其它父类的参数
 *      }
 */
export default class SoftLineMaterial extends HardLineMaterial{
    constructor(values={}){
        super(values);
    }

    //......................................................public......................................................

    get zoomFactor(){
        return this._zoomFactor;
    }
    set zoomFactor(num){
        this.uniforms.zoomFactor.value=this._zoomFactor=num;
    }

    //.....................................................private......................................................

    _initVariable(values) {
        super._initVariable(values);
        this._zoomFactor=values.zoomFactor||1;
    }
    _initUniforms() {
        super._initUniforms();
        this.uniforms.zoomFactor={value:this._zoomFactor};
        this.needsUpdate=true;
    }
    _initVertexShader() {
        this.vertexShader=`
            #define MAX_NODE_RAT 1.78
            attribute vec3 nextPosition;
            attribute vec3 prePosition;
            attribute vec3 dirPosition;
            attribute float dashMark;
            attribute float offset;
            attribute float lineDistance;
            uniform float width;
            uniform float perspectiveFactor;
            uniform bool sizeAttenuation;
            uniform float zOffset;
            uniform float tolLength;
            uniform float zoomFactor;
            varying float vDistance;
            varying float vDashMark;
            varying vec2 vuv;
            float angleOfVec(vec3 a,vec3 b){
               float d=dot(a,b);
               float sa=a.x*a.x+a.y*a.y+a.z*a.z;
               float sb=b.x*b.x+b.y*b.y+b.z*b.z;
               float theta=d/sqrt(sa*sb);
               return acos(clamp(theta,-1.0,1.0));
            }
            float computeAspect(){
               float aspect=0.5625;
               if(projectionMatrix[3][3]==0.0){
                  float _tan=projectionMatrix[1][1];
                  float as_tan=1.0/projectionMatrix[0][0];
                  aspect=1.0/(as_tan*_tan);
               }else{
                  float _height=1.0/projectionMatrix[1][1];
                  float _width=1.0/projectionMatrix[0][0];
                  aspect=_height/_width;
               }
               return aspect;
            }
            void main(){
               vec4 pmvPosition=projectionMatrix*modelViewMatrix*vec4(position,1.0);
               vec4 pmvNextPosition=projectionMatrix*modelViewMatrix*vec4(nextPosition,1.0);
               vec4 pmvDirPosition=projectionMatrix*modelViewMatrix*vec4(dirPosition,1.0);
               vec4 pmvPrePosition=projectionMatrix*modelViewMatrix*vec4(prePosition,1.0);
               vec3 nxtP=pmvNextPosition.xyz/abs(pmvNextPosition.w);
               vec3 curP=pmvPosition.xyz/abs(pmvPosition.w);
               vec3 dirP=pmvDirPosition.xyz/abs(pmvDirPosition.w);
               vec3 preP=pmvPrePosition.xyz/abs(pmvPrePosition.w);
               vec3 look=vec3(0.0,0.0,1.0);
               vec3 doubleDir=nxtP-curP;
               vec3 CPP=curP-preP;
               vec3 DCP=dirP-curP;

               float aspect=computeAspect();
               vec3 tripleDir=normalize(CPP)+normalize(DCP);
               doubleDir.y*=aspect;
               tripleDir.y*=aspect;
               vec3 doubleCross=normalize(cross(look,doubleDir));
               vec3 tripleCross=normalize(cross(look,tripleDir));
               doubleCross.x*=aspect;
               tripleCross.x*=aspect;
               float DTAngle=abs(angleOfVec(-CPP,DCP));
               vec3 dirCross=normalize(cross(-CPP,DCP));
               float dirDot=dot(look,dirCross);
               float sAngle=1.5707963-DTAngle*0.5;
               float cv=cos(sAngle);
               float dWidth=width;

               if(projectionMatrix[3][3]!=0.){
                   if(sizeAttenuation){
                       dWidth*=projectionMatrix[1][1];
                   }
               }

               dWidth=dWidth/cv;
               if(dWidth>MAX_NODE_RAT*width){
                  dWidth=MAX_NODE_RAT*width;
               }
               vec3 offsetVec=vec3(0.);

               if(dirDot>0.0){
                  if(offset>0.0){
                     if(sizeAttenuation){
                        offsetVec=offset*doubleCross*dWidth/perspectiveFactor;
                     }else{
                        offsetVec=offset*doubleCross*dWidth/perspectiveFactor*pmvPosition.w;
                     }
                     gl_Position=vec4(vec3(pmvPosition.xyz)+offsetVec,pmvPosition.w);
                  }else{
                     if(sizeAttenuation){
                        offsetVec=tripleCross*dWidth/perspectiveFactor;
                     }else{
                        offsetVec=tripleCross*dWidth/perspectiveFactor*pmvPosition.w;
                     }
                     gl_Position=vec4(vec3(pmvPosition.xyz)-offsetVec,pmvPosition.w);
                  }
               }else{
                  if(offset>0.0){
                     if(sizeAttenuation){
                        offsetVec=tripleCross*dWidth/perspectiveFactor;
                     }else{
                        offsetVec=tripleCross*dWidth/perspectiveFactor*pmvPosition.w;
                     }
                     gl_Position=vec4(vec3(pmvPosition.xyz)+offsetVec,pmvPosition.w);
                  }else{
                     if(sizeAttenuation){
                        offsetVec=doubleCross*dWidth/perspectiveFactor;
                     }else{
                        offsetVec=doubleCross*dWidth/perspectiveFactor*pmvPosition.w;
                     }
                     gl_Position=vec4(vec3(pmvPosition.xyz)-offsetVec,pmvPosition.w);
                  }
               }
               vDistance=lineDistance;
               vuv=vec2(lineDistance*zoomFactor,sign(offset)*0.5);
               vDashMark=dashMark;
            }
        `;
    }

    _getExclusiveKeys() {
        let ks= super._getExclusiveKeys();
        ks.push('zoomFactor');
        return ks;
    }
}